#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include "maz/assert.h"

int dlvl = DINF;

#define MAZ_STREAM_TYPE_AUDIO   0
#define MAZ_STREAM_TYPE_VIDEO   1

typedef struct _HEADER_
{
    char        sync[4];            // H3C_
    uint32_t    type;               // 码流类型 0:音频;  1:视频
    uint32_t    pack;               // 封装类型 0:ES;    1:PS
    uint32_t    atype;              // 音频编码 0:PCM;   1:G711A; 2:G711U; 3:G726_16; 4:G726_24; 5:G726_32; 6:G726_40; 7:AAC_LC
    uint32_t    vtype;              // 视频编码 0:H.264; 1:H.265
    uint32_t    ftype;              // 帧类型   0:I;     1:P;     2:B
    uint32_t    chan;               // 通道号
    uint32_t    len;                // 长度
    uint64_t    pts;                // 时间戳
    uint32_t    reserve[2];
} HEADER;

int maz_split(char *iname);

int main(int argc, char *argv[])
{
    int rcnt = 0;                   // read count
    int wcnt = 0;                   // write count
    int scnt = 0;                   // stream count

    char *iname = NULL;
    char *aname = "a.aac";
    char *vname = "v.h265";
    FILE *afile = NULL;             // audio input file
    FILE *vfile = NULL;             // video input file

    FILE *bfile = NULL;             // bin  output file
    uint8_t *buf = NULL;
    HEADER hd = { 0 };

    if (argc != 2)
    {
        dlog(DERR, "usage: %s <bin>\n", argv[0]);
        return -1;
    }

    iname = argv[1];

    // 打开输入bin文件
    bfile = fopen(iname, "rb");
    MAZASSERT_RETVAL(!bfile, -1, "err: fopen %s", iname);

    // 创建音频和视频文件
    afile = fopen(aname, "wb");
    MAZASSERT_RETVAL(!afile, -1, "err: fopen %s", aname);

    vfile = fopen(vname, "wb");
    MAZASSERT_RETVAL(!vfile, -1, "err: fopen %s", vname);

    // 申请缓存
    buf = malloc(10 * 1024 * 1024);

    // 循环读取文件
    while(1)
    {
        // 读取码流信息头
        memset(&hd, 0, sizeof(HEADER));
        rcnt = fread(&hd, 1, sizeof(HEADER), bfile);
        MAZASSERT_BRK_NOMSG(rcnt != sizeof(HEADER));

        // 判断码流同步码
        MAZASSERT_BRK(hd.sync[0] != 'H' || hd.sync[1] != '3' || hd.sync[2] != 'C' || hd.sync[3] != '_', "err: sync = %s", hd.sync);

        // 读取bin文件, 取出一帧码流数据
        rcnt = fread(buf, 1, hd.len, bfile);
        MAZASSERT_BRK(rcnt != hd.len, "err: read %s frame failed", iname);
        scnt++;

        dlog(DINF, "[%04d] type:%d len:%d", scnt, hd.type, hd.len);

        if(hd.type == MAZ_STREAM_TYPE_AUDIO)
        {
            wcnt = fwrite(buf, 1, hd.len, afile);
            MAZASSERT_BRK(wcnt != hd.len, "err: fwrite %s audio frame header", aname);
        }
        else if(hd.type == MAZ_STREAM_TYPE_VIDEO)
        {
            wcnt = fwrite(buf, 1, hd.len, vfile);
            MAZASSERT_BRK(wcnt != hd.len, "err: fwrite %s video frame header", vname);
        }
    }

    // 关闭文件
    fclose(afile);
    fclose(vfile);
    fclose(bfile);

    return 0;
}
